<!--web端 动态路由的管理页面：对菜单(路由)的增删改查-->

<template>
  <div class="app-container">
    <div class="filter-container" style="display: flex; margin: 0 auto; justify-content: space-between;">
      <div />
      <div style="margin-right: 50px;">
        <!--src/directive/permission/index.js 自定义权限指令v-permission-->
        <el-button
          v-permission="['iam:webMenu:create']"
          v-waves
          type="primary"
          class="filter-item"
          plain
          size="mini"
          @click="onCreateItem"
        >新增
        </el-button>
        <el-button
          v-permission="['iam:webMenu:edit']"
          v-waves
          type="primary"
          class="filter-item"
          plain
          size="mini"
          :disabled="itemSelectedId === undefined"
          @click="onEditItem"
        >修改
        </el-button>
        <el-button
          v-permission="['iam:webMenu:delete']"
          v-waves
          type="primary"
          class="filter-item"
          plain
          size="mini"
          :disabled="itemSelectedId === undefined"
          @click="onRemoveItem"
        >删除
        </el-button>
      </div>
    </div>

    <el-table
      ref="itemTable"
      v-loading="itemListLoading"
      v-el-height-adaptive-table="{bottomOffset: 30}"
      row-key="id"
      :data="itemList"
      border
      fit
      highlight-current-row
      class="item-table"
      height="100px"
      @selection-change="onItemTableSelectionChange"
      @row-click="onItemRowClick"
    >
      <el-table-column
        type="selection"
        width="55"
      />
      <el-table-column
        prop="name"
        header-align="center"
        width="240"
        label="菜单名称"
      />
      <el-table-column
        prop="type.label"
        header-align="center"
        align="center"
        width="100"
        label="类型"
      />
      <el-table-column
        prop="openType.label"
        header-align="center"
        align="center"
        width="100"
        label="打开方式"
      />
      <el-table-column
        prop="sortNo"
        header-align="center"
        align="center"
        width="100"
        label="排序"
      />
      <el-table-column
        prop="permissions"
        header-align="center"
        :show-overflow-tooltip="true"
        label="权限标识"
      />
    </el-table>

    <!--新增或编辑窗口-->
    <el-drawer
      ref="editDrawer"
      :title="dataForm.id ? '编辑菜单' : '新增菜单'"
      :visible.sync="showEditDrawer"
      direction="rtl"
      custom-class="demo-drawer"
      size="50%"
      :close-on-press-escape="drawerCloseOnEsc"
      :wrapper-closable="drawerWrapperClosable"
    >
      <div class="edit-drawer-content">
        <el-form ref="dataForm" :model="dataForm" :rules="dataFormRule" label-width="80px">
          <el-row :gutter="23">
            <el-col :span="23">
              <el-form-item label="类型" prop="type">
                <el-select v-model="dataForm.type" placeholder="请选择菜单类型" style="width: 100%;">
                  <el-option
                    v-for="item in menuTypeList"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="23">
            <el-col :span="23">
              <el-form-item label="名称" prop="name">
                <el-input v-model="dataForm.name" placeholder="请输入菜单名称" />
              </el-form-item>
            </el-col>
          </el-row>
          <!--下拉选择菜单组-->
          <el-row :gutter="23">
            <el-col :span="23">
              <el-form-item label="上级菜单" prop="parentId">
                <el-select-tree
                  v-model="dataForm.parentId"
                  style="width: 100%;"
                  :data="menuGroupList"
                  :props="{
                    value: 'id',
                    label: (data) => data.name,
                    children: 'children'
                  }"
                  placeholder="请选择上级菜单"
                  default-expand-all
                  check-strictly
                />
              </el-form-item>
            </el-col>
          </el-row>

          <!--判断类型：菜单组or菜单，菜单才显示打开方式、链接地址-->
          <div v-if="dataForm.type === 'menu'" style="width: 100%">
            <el-row :gutter="23">
              <el-col :span="23">
                <el-form-item label="打开方式" prop="openType">
                  <el-select v-model="dataForm.openType" placeholder="请选择菜单打开方式" style="width: 100%;">
                    <el-option
                      v-for="item in menuOpenTypeList"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>

            <el-row :gutter="23">
              <el-col :span="23">
                <el-form-item label="链接地址" prop="link">
                  <el-input v-model="dataForm.link" placeholder="请输入菜单链接地址" />
                </el-form-item>
              </el-col>
            </el-row>
          </div>

          <el-row :gutter="23">
            <el-col :span="23">
              <el-form-item label="菜单图标" prop="icon" style="width: 100%;">
                <!--图标选择组件-->
                <icon-select v-model="dataForm.icon" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="23">
            <el-col :span="23">
              <el-form-item label="菜单排序" prop="sortNo" style="width: 100%;">
                <el-input-number v-model="dataForm.sortNo" placeholder="请输入菜单排序" style="width: 100%" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="23">
            <el-col :span="23">
              <el-form-item label="权限标识" prop="permissions">
                <el-input v-model="dataForm.permissions" placeholder="请输入菜单权限标识" />
              </el-form-item>
            </el-col>
          </el-row>

        </el-form>
      </div>
      <div class="edit-drawer-footer">
        <el-button
          v-waves
          class="filter-item"
          plain
          size="mini"
          @click="showEditDrawer = false"
        >取消
        </el-button>

        <el-button
          v-waves
          class="filter-item"
          size="mini"
          type="primary"
          @click="onSaveData"
        >保存
        </el-button>
      </div>
    </el-drawer>
  </div>
</template>

<script>
// 导入自定义权限指令v-permission
import permission from '@/directive/permission/index.js'
import waves from '@/directive/waves'
import elHeightAdaptiveTable from '@/directive/el-table'
import WebMenuApi from '@api/iam/webMenu.js'
import CommonApi from '@api/sys/common.js'
import { treeDataTranslate, resetObject, fillObject } from '@utils/index'
// 导入自定义的图标选择组件
import IconSelect from '@components/IconSelect'
import { validURL } from '@utils/validate'
import Settings from '@/settings'

let self

// 对输入数据进行校验
const validateOpenType = (rule, value, callback) => {
  if (!self) {
    callback()
    return
  }
  if (self.dataForm.type === 'menu') {
    if (!value) {
      callback(new Error('请选择打开方式'))
    }
  }

  callback()
}

const validateLink = (rule, value, callback) => {
  if (!self) {
    callback()
    return
  }
  if (self.dataForm.type === 'menu') {
    if (!value) {
      callback(new Error('请输入菜单链接'))
      return
    }

    if (!self.dataForm.openType) {
      callback()
      return
    }

    if (self.dataForm.openType === 'router') {
      if (!value.startsWith('/')) {
        callback(new Error('请输入正确的内部路由地址'))
        return
      }
    } else {
      if (!validURL(value)) {
        callback(new Error('请输入正确的外部链接地址'))
        return
      }
    }
  }

  callback()
}

export default {
  name: 'IamWebMenuList',
  // 注册图标选择组件
  components: { IconSelect },
  directives: { permission, waves, elHeightAdaptiveTable },
  data() {
    return {
      menuOpenTypeList: [],
      menuTypeList: [],
      menuGroupList: [],
      itemList: [],
      itemListLoading: false,
      showEditDrawer: false,
      itemSelectedId: undefined,
      drawerCloseOnEsc: Settings.drawerCloseOnEsc,
      drawerWrapperClosable: Settings.drawerWrapperClosable,
      dataForm: {
        id: undefined,
        parentId: undefined,
        name: undefined,
        type: undefined,
        icon: undefined,
        openType: undefined,
        link: undefined,
        permissions: undefined,
        sortNo: undefined
      },
      dataFormRule: {
        name: [
          { required: true, message: '请输入菜单名称', trigger: 'blur' }
        ],
        parentId: [
          { required: true, message: '请选择上级菜单', trigger: 'blur' }
        ],
        type: [
          { required: true, message: '请选择菜单类型', trigger: 'blur' }
        ],
        openType: [
          { validator: validateOpenType, trigger: 'blur' }
        ],
        link: [
          { validator: validateLink, trigger: 'blur' }
        ]
      }
    }
  },
  computed: {},
  created(query) {
    self = this
    this.loadDependParams()
    this.loadGroupList()
    this.loadItemList()
  },
  methods: {
    loadDependParams() {
      // 获取菜单类型：菜单组、菜单、(按钮)
      CommonApi.fetchEnumList({ type: 'com.codol.zhty.modules.iam.enums.MenuType', includes: ['group', 'menu'] }).then(response => {
        const { list } = response.data
        this.menuTypeList.splice(0, this.menuTypeList.length, ...list)
      })
      // 获取菜单打开方式：(无)、内部路由、内部框架、新窗口
      CommonApi.fetchEnumList({ type: 'com.codol.zhty.modules.iam.enums.MenuOpenType', includes: ['router', 'iframe', 'window'] }).then(response => {
        const { list } = response.data
        this.menuOpenTypeList.splice(0, this.menuOpenTypeList.length, ...list)
      })
    },
    // 获取菜单组列表
    loadGroupList() {
      WebMenuApi.fetchList({ includeSelf: true, includeRoot: false, types: ['group'] }).then(response => {
        const { list } = response.data
        // treeDataTranslate(list)树形数据转换 src/utils/index.js
        this.menuGroupList = treeDataTranslate(list)
      })
    },
    // 获取菜单列表
    loadItemList() {
      this.itemListLoading = true

      if (this.$refs.itemTable) {
        this.$refs.itemTable.clearSelection()
      }
      WebMenuApi.fetchList({ includeSelf: false, includeRoot: false }).then(response => {
        const { list } = response.data
        this.itemList = treeDataTranslate(list)
      }).finally(() => {
        this.itemListLoading = false
      })
    },
    onItemTableSelectionChange(array) {
      if (array.length > 1) {
        this.$refs.itemTable.clearSelection()
        this.$refs.itemTable.toggleRowSelection(array.pop())
        return
      }
      if (array[0]) {
        this.itemSelectedId = array[0].id
      } else {
        this.itemSelectedId = undefined
      }
    },
    // 新增菜单
    onCreateItem() {
      resetObject(this.dataForm)
      this.showEditDrawer = true
    },
    onItemRowClick(item) {
      // openType打开方式；type菜单类型
      fillObject(this.dataForm, item, undefined, ['openType', 'type'])
      this.dataForm.type = item.type.value
      this.dataForm.openType = item.openType.value
      this.showEditDrawer = true
    },
    // 编辑菜单
    onEditItem() {
      if (!this.$refs.itemTable) {
        return
      } else if (this.$refs.itemTable.selection.length !== 1) {
        return
      }
      const item = this.$refs.itemTable.selection[0]
      fillObject(this.dataForm, item, undefined, ['openType', 'type'])
      this.dataForm.type = item.type.value
      this.dataForm.openType = item.openType.value
      this.showEditDrawer = true
    },
    // 保存
    onSaveData() {
      const dataForm = this.$refs.dataForm
      dataForm.validate((valid) => {
        if (!valid) {
          return
        }
        // 验证通过，执行保存方法
        this.doSaveData()
      })
    },
    doSaveData() {
      WebMenuApi.save(this.dataForm).then(response => {
        // 关闭新增或编辑窗口
        this.showEditDrawer = false
        // 重置对象
        resetObject(this.dataForm)
        this.loadGroupList()
        this.loadItemList()
      })
    },
    // 删除
    onRemoveItem() {
      if (!this.$refs.itemTable) {
        return
      } else if (this.$refs.itemTable.selection.length !== 1) {
        return
      }

      const item = this.$refs.itemTable.selection[0]
      this.$confirm(`确定删除菜单【${item.name}】及其子菜单`, '提示').then(() => {
        self.doRemoveItem(item)
      })
    },
    doRemoveItem(item) {
      WebMenuApi.remove(item.id).then(() => {
        this.loadGroupList()
        this.loadItemList()
      })
    }
  }
}
</script>

<style scoped>

</style>
